﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Windows.Forms;

namespace SimpleChat
{
    // 消息结构定义
    namespace MsgStruct
    {
        // ========== 连接相关消息 ==========
        public struct LoginRequest // 登录请求
        {
            public string ID;
            public string Password;
        }

        public struct LoginResponse // 登录响应
        {
            public bool IsSuccess;    // 登录成功与否
            public string UserName;   // 登录成功后返回用户名
        }

        public struct OnlineState // 上线状态
        {
            public string ID;
            public bool IsOnline;
        }

        // ========== 用户关系消息 ==========
        public struct UserInfo
        {
            public string Name;
            public string UserID;        // 用户ID
            public bool OnlineState;     // 在线状态
        }

        public struct UserListUpdate // 用户列表更新
        {
            public UserInfo[] UserInfos;
        }

        public struct AddFriend // 添加好友请求
        {
            public string RequesterID; // 请求者ID
            public string TargetID;    // 目标用户ID
        }

        public struct DeleteFriend // 删除好友请求
        {
            public string RequesterID; // 请求者ID
            public string TargetID;    // 目标用户ID
        }

        // ========== 聊天消息 ==========
        public struct PrivateMessage // 私聊消息
        {
            public string SenderID;
            public string ReceiverID;
            public string Content;
        }

        // ========== 系统消息 ==========
        public struct SystemMessage // 系统通知
        {
            public string Content;
        }

        public struct ErrorMessage // 错误消息
        {
            public int ErrorCode;
            public string ErrorInfo;
        }
    }

    // 消息类型枚举
    public enum MessageType
    {
        // ========== 连接相关消息 ==========
        LoginRequest,     // 登录请求
        LoginResponse,    // 登录响应
        OnlineState,      // 上线状态

        // ========== 用户关系消息 ==========
        UserListUpdate,   // 用户列表更新
        AddFriend,        // 添加好友请求
        DeleteFriend,     // 删除好友请求

        // ========== 聊天消息 ==========
        PrivateMessage,   // 私聊消息

        // ========== 系统消息 ==========
        System,           // 系统通知
        Error,            // 错误消息

        // ========== 预留扩展 ==========
        // Image,        // 图片消息（预留）
        // File,         // 文件传输（预留）
        // GroupMessage, // 群组消息（预留）
        // Heartbeat,    // 心跳检测（预留）
        // Ack           // 确认收到（预留）
        // StatusUpdate  // 状态更新
    }

    // 消息包装结构
    public struct Message
    {
        public MessageType Type;
        // public DateTime DateTime; // 暂时不传输时间，启用使用时需要配置json序列化转换器
        public string Msg;
    }

    // IP配置类
    public class IPConfig
    {
        public string ServerIPv4 { get; set; }
        public int ServerPort { get; set; }
    }

    // 消息管理器
    public class MessageManager
    {
        private readonly List<Message> receivedMessages = new List<Message>();// 接收到的消息队列
        private readonly Queue<Message> messagesToSend = new Queue<Message>();// 待发送的消息队列
        private readonly object receiveLock = new object();// 接收锁
        private readonly object sendLock = new object();// 发送锁
        private readonly object connectionLock = new object();// 连接锁

        private Socket client;
        private Thread receiveThread;// 接收线程
        private Thread sendThread;// 发送线程
        private CancellationTokenSource cancellationTokenSource;
        private bool isReconnecting;// 是否正在重连
        private int reconnectAttempts;// 重连尝试次数
        private System.Threading.Timer reconnectTimer;// 重连定时器

        public IPConfig IPConfig { get; set; }
        public bool isConnected => client != null && client.Connected;
        public event EventHandler<MessageEventArgs> MessageReceived;
        public event EventHandler<ConnectionEventArgs> ConnectionChanged;

        private static readonly Lazy<MessageManager> lazyInstance =
            new Lazy<MessageManager>(() => new MessageManager());//使用Lazy进行线程安全的单例模式

        public static MessageManager Instance => lazyInstance.Value;

        //-------------------------------------------------优美-分割线--------------------------------------------------//

        private MessageManager()
        {
            reconnectTimer = new System.Threading.Timer(ReconnectCallback, null, Timeout.Infinite, Timeout.Infinite);
        }

        public void Initialize()
        {
            IPConfig = LoadIPConfig();
        }

        public static IPConfig LoadIPConfig(string filePath = "Config.json")
        {
            try
            {
                // 检查文件是否存在
                if (!File.Exists(filePath))
                {
                    throw new FileNotFoundException("IP配置文件不存在", filePath);
                }

                // 读取文件内容
                string jsonContent = File.ReadAllText(filePath, Encoding.UTF8);

                // 反序列化为IPConfig对象（忽略大小写，避免JSON键名大小写问题）
                JsonSerializerOptions options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true // 允许JSON中的键名与类属性大小写不一致
                };
                IPConfig config = JsonSerializer.Deserialize<IPConfig>(jsonContent, options);

                // 验证配置有效性（IP和端口不能为空）
                if (string.IsNullOrEmpty(config.ServerIPv4) || config.ServerPort <= 0 || config.ServerPort > 65535)
                {
                    throw new ArgumentException("IP配置文件内容无效（IP为空或端口不在有效范围1-65535）");
                }

                return config;
            }
            catch (Exception ex)
            {
                // 处理读取或解析错误（如日志记录、弹窗提示等）
                Console.WriteLine($"加载IP配置失败：{ex.Message}");
                // 可根据需求返回默认配置（如本地测试地址）
                return new IPConfig { ServerIPv4 = "127.0.0.1", ServerPort = 8888 };
            }
        }

        public void ConnectReset()
        {
            // 先终止旧线程（关键修复）
            Stop();

            lock (connectionLock)
            {
                reconnectTimer?.Change(Timeout.Infinite, Timeout.Infinite);
                isReconnecting = false;
                reconnectAttempts = 0;
                client = null; // 已在Stop()中关闭，这里直接置空
                OnConnectionChanged(false, null);
            }
        }
        public void UpdateMessageManagerConfig()
        {
            // 先重置连接相关状态（定时器、重连次数等）
            MessageManager.Instance.ConnectReset();
            // 应用新配置并重新启动
            MessageManager.Instance.Initialize();
            MessageManager.Instance.Start();
        }

        public void Start()
        {
            cancellationTokenSource?.Cancel(); // 确保旧令牌被取消
            cancellationTokenSource = new CancellationTokenSource();

            // 无论旧线程是否存活，都创建新线程（旧线程会因令牌取消而退出）
            receiveThread = new Thread(ReceiveLoop) { IsBackground = true };
            sendThread = new Thread(SendLoop) { IsBackground = true };

            receiveThread.Start();
            sendThread.Start();

            Connect(); // 强制触发连接
        }

        public void Stop()
        {
            cancellationTokenSource?.Cancel();
            reconnectTimer?.Change(Timeout.Infinite, Timeout.Infinite);

            lock (connectionLock)
            {
                try { client?.Close(); } catch { }
                client = null;
            }

            // 延长等待时间，确保线程有足够时间退出
            try { receiveThread?.Join(3000); } catch { }
            try { sendThread?.Join(3000); } catch { }

            // 若线程仍未退出，强制置空（避免影响新线程创建）
            receiveThread = null;
            sendThread = null;
        }

        public void SendMessage(Message msg)
        {
            lock (sendLock)
            {
                messagesToSend.Enqueue(msg);
                Monitor.Pulse(sendLock);
            }
        }

        private void Connect()
        {
            lock (connectionLock)
            {
                isReconnecting = false;
                if (isConnected || isReconnecting) return;

                try
                {
                    if (client != null)
                    {
                        try { client.Close(); } catch { }
                        client = null;
                    }

                    client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    client.Connect(IPConfig.ServerIPv4, IPConfig.ServerPort);

                    reconnectAttempts = 0;
                    isReconnecting = false;

                    OnConnectionChanged(true, null);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"连接失败: {ex.Message}");
                    ScheduleReconnect();
                    OnConnectionChanged(false, ex);
                }
            }
        }

        private void ScheduleReconnect()
        {
            lock (connectionLock)
            {
                if (isReconnecting || cancellationTokenSource.IsCancellationRequested) return;

                isReconnecting = true;
                reconnectAttempts++;

                // 指数退避重连策略
                int delay = Math.Min(30000, 500 * (int)Math.Pow(2, reconnectAttempts));
                reconnectTimer.Change(delay, Timeout.Infinite);

                Console.WriteLine($"计划在 {delay / 1000} 秒后尝试重连 (尝试 {reconnectAttempts})");
            }
        }

        private void ReconnectCallback(object state)
        {
            if (cancellationTokenSource.IsCancellationRequested) return;
            Connect();
        }

        private void ReceiveLoop()
        {
            try
            {
                byte[] buffer = new byte[4096];

                while (!cancellationTokenSource.IsCancellationRequested)
                {
                    try
                    {
                        if (!isConnected)
                        {
                            Thread.Sleep(1000);
                            continue;
                        }

                        int bytesRead = client.Receive(buffer);
                        if (bytesRead == 0) throw new SocketException((int)SocketError.ConnectionReset);

                        string json = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                        Message msg = JsonSerializer.Deserialize<Message>(json);

                        lock (receiveLock)
                        {
                            receivedMessages.Add(msg);
                            Monitor.Pulse(receiveLock);
                        }

                        OnMessageReceived(msg);
                    }
                    catch (SocketException ex)
                    {
                        Console.WriteLine($"接收消息时发生Socket异常: {ex.SocketErrorCode} - {ex.Message}");
                        HandleDisconnect();
                    }
                    catch (JsonException ex)
                    {
                        Console.WriteLine($"JSON解析错误: {ex.Message}");
                        Console.WriteLine($"错误的JSON数据: {Encoding.UTF8.GetString(buffer)}");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"接收消息时发生未知异常: {ex.Message}");
                        HandleDisconnect();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"接收线程异常退出: {ex.Message}");
            }
        }

        private void SendLoop()
        {
            try
            {
                while (!cancellationTokenSource.IsCancellationRequested)
                {
                    Message message = default;
                    bool hasMessage = false;

                    lock (sendLock)
                    {
                        while (messagesToSend.Count == 0 && !cancellationTokenSource.IsCancellationRequested)
                        {
                            Monitor.Wait(sendLock);
                        }

                        if (messagesToSend.Count > 0)
                        {
                            message = messagesToSend.Dequeue();
                            hasMessage = true;
                        }
                    }

                    if (hasMessage)
                    {
                        try
                        {
                            if (!isConnected)
                            {
                                Console.WriteLine("尝试重连以发送消息");
                                Connect();

                                // 如果仍然未连接，将消息放回队列
                                if (!isConnected)
                                {
                                    lock (sendLock)
                                    {
                                        messagesToSend.Enqueue(message);
                                    }
                                    Thread.Sleep(1000);
                                    continue;
                                }
                            }

                            string json = JsonSerializer.Serialize(message);
                            byte[] data = Encoding.UTF8.GetBytes(json);
                            client.Send(data);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"发送消息失败: {ex.Message}");

                            // 将消息放回队列重试
                            lock (sendLock)
                            {
                                messagesToSend.Enqueue(message);
                            }

                            HandleDisconnect();
                            Thread.Sleep(1000);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发送线程异常退出: {ex.Message}");
            }
        }

        private void HandleDisconnect()
        {
            lock (connectionLock)
            {
                try { client?.Close(); } catch { }
                client = null;

                Console.WriteLine("连接已断开，准备重连");
                ScheduleReconnect();
                OnConnectionChanged(false, null);
            }
        }

        protected virtual void OnMessageReceived(Message msg)
        {
            MessageReceived?.Invoke(this, new MessageEventArgs { Message = msg });
        }

        protected virtual void OnConnectionChanged(bool isConnected, Exception exception)
        {
            ConnectionChanged?.Invoke(this, new ConnectionEventArgs
            {
                IsConnected = isConnected,
                Exception = exception
            });
        }
    }

    // 事件参数类
    public class MessageEventArgs : EventArgs
    {
        public Message Message { get; set; }
    }

    public class ConnectionEventArgs : EventArgs
    {
        public bool IsConnected { get; set; }
        public Exception Exception { get; set; }
    }
}